<template>
  <div class="layer-panel">
    <el-tree
      style="max-width: 350px"
      :data="layerData"
      :props="defaultProps"
      show-checkbox
      node-key="id"
      :default-expanded-keys="defaultExpandedKeys"
      @check-change="handleCheckChange"
    />
  </div>
</template>

<script setup>
import { reactive, toRefs, onMounted } from "vue";

const props = defineProps({
  map: {
    type: Object,
    required: true,
  },
});
let sources = [];
const data = reactive({
  layerData: [
    {
      id: "10",
      label: "测试geojson数据",
      children: [
        {
          id: "1",
          label: "行道树",
          url: `${import.meta.env.VITE_JSON_BASE_URL}/json/行道树.json`,
          layerId: "xds",
          layerType: "geojson",
          // 要素类型
          featureType: "symbol",
          // 图片
          markerUrl: `${import.meta.env.VITE_JSON_BASE_URL}/images/行道树.png`,
        },
        {
          id: "2",
          label: "10w点加载测试",
          url: `${import.meta.env.VITE_JSON_BASE_URL}/json/geojson_data.json`,
          layerId: "geojson_10w",
          layerType: "geojson",
          // 要素类型
          featureType: "circle",
        },
        {
          id: "3",
          label: "30w点加载测试",
          url: `${
            import.meta.env.VITE_JSON_BASE_URL
          }/json/geojson_data_30w.json`,
          layerId: "geojson_30w",
          layerType: "geojson",
          // 要素类型
          featureType: "circle",
        },
        {
          id: "4",
          label: "苏州行政区划",
          url: `${import.meta.env.VITE_JSON_BASE_URL}/json/suzhou_xzqh.json`,
          layerId: "szs-lunkuo",
          layerType: "geojson",
          // 要素类型
          featureType: "line",
        },
      ],
    },
  ],
  defaultProps: {
    children: "children",
    label: "label",
    disabled: "disabled",
  },
  defaultExpandedKeys: ["10"],
});

const handleCheckChange = (nodeData, checked) => {
  // 只处理子节点
  if (nodeData.children) return;
  if (checked) {
    if (nodeData.layerType === "geojson") {
      if (nodeData.markerUrl) {
        loadImage(nodeData, () => {
          loadGeojsonData(nodeData);
        });
      } else {
        loadGeojsonData(nodeData);
      }
    }
  } else {
    removeLayerById(nodeData.layerId);
  }
};

// 封装加载 GeoJSON 数据的函数
const loadGeojsonData = (params) => {
  const { url, layerId, featureType, paint, layout } = params;
  fetch(url)
    .then((response) => response.json())
    .then((res) => {
      if (!props.map.getSource(layerId)) {
        props.map.addSource(layerId, {
          type: "geojson",
          data: res,
        });
        sources.push(layerId);
      }
      let obj = {
        id: layerId,
        type: featureType,
        source: layerId,
        paint: paint || getDefaultPaint(params),
        layout:
          featureType === "symbol" ? layout || getDefaultLayout(params) : {},
      };
      props.map.addLayer(obj);
    });
};

// 根据图层类型返回不同的 paint 配置
const getDefaultPaint = (params) => {
  const { featureType } = params;
  switch (featureType) {
    case "circle":
      return {
        "circle-color": "#007cbf",
        "circle-radius": 4,
        "circle-stroke-width": 1,
        "circle-stroke-color": "#fff",
      };
    case "line":
      return {
        "line-color": "#0fe0e7",
        "line-width": 5,
      };
    case "symbol":
      return {
        "text-color": "#ffffff", //设置颜色
      };
    // 可以根据需要添加更多类型
    default:
      return {};
  }
};
// 返回默认的layout
const getDefaultLayout = (params) => {
  const { featureType, layerId } = params;
  switch (featureType) {
    case "symbol":
      return {
        "icon-image": layerId + "-icon",
        "icon-size": 0.02,
        "icon-ignore-placement": true,
        "icon-allow-overlap": true,
        "icon-keep-upright": true,
      };
  }
};

// 加载图片
const loadImage = (params, func) => {
  const { markerUrl, layerId } = params;
  props.map.loadImage(markerUrl, function (err, image) {
    if (err) {
      console.error(err);
    } else {
      props.map.addImage(layerId + "-icon", image);
      func();
    }
  });
};

// 根据layerId删除layer
const removeLayerById = (id) => {
  props.map.removeLayer(id);
};

// 循环删除source
const removeAllSources = () => {
  sources.forEach((sourceId) => {
    if (props.map.getLayer(sourceId)) {
      props.map.removeLayer(sourceId);
    }
    props.map.removeSource(sourceId);
  });
  sources = [];
};

const { layerData, defaultProps, defaultExpandedKeys } = toRefs(data);
defineExpose({
  removeAllSources,
});
</script>

<style lang="scss" scoped>
.layer-panel {
  position: absolute;
  top: 36px;
  right: 0;
  min-width: 240px;
  padding: 20px 14px;
  background-color: #fff;
}
</style>
